/**
 * @file   list.c
 * @brief  linked list control
 *
 * @date   2011/04/23
 * @author K.Akasaka
 *
 */
#include "core/include/types.h"
#include "core/include/list.h"

/**
 * @brief  get the list item from target list.
 *
 * @param  **lst target list
 * @return list item on the top of target list
 * @retval null exceptionally
 * @retval not null normally
 */
LIST_ITEM *popFromList(LIST_ITEM **lst)
{
	if(*lst == NULL)
	{
		return NULL;
	}
	else
	{
		LIST_ITEM *retItm = *lst;
		*lst = (*lst)->next;

		retItm->next = NULL;

		return retItm;
	}
}


/**
 * @brief  link the list item to the tail of target list.
 *
 * @param  **lst target list
 * @param  *itm list item for linking
 * @return new linked list
 * @retval null exceptionally
 * @retval not null normally
 */
LIST_ITEM *pushToList(LIST_ITEM **lst, LIST_ITEM *itm)
{
	if(*lst == NULL) {
		*lst = itm;
	} else if(itm == NULL){
		// do nothing
	} else {
		LIST_ITEM *ptr = *lst;

		while(ptr->next != NULL)
		{
			ptr = ptr->next;
		}

		ptr->next = itm;
		itm->next = NULL;
	}

	return *lst;
}


/**
 * @brief  Search the item with the target load in the list
 *
 * @param  **lst target list
 * @param  *load the load to search
 * @return list item that has the target load
 * @retval null exceptionally
 * @retval not null normally
 */
LIST_ITEM *searchInList(LIST_ITEM **lst, void *load)
{
	LIST_ITEM *ptr = *lst;

	while(ptr != NULL || ptr->load != load)
	{
		ptr = ptr->next;
	}

	if(ptr == NULL)
	{
		return NULL;
	}
	else
	{
		return ptr;
	}
}

LIST_ITEM *deleteFromList(LIST_ITEM **lst, LIST_ITEM *tgt)
{
	LIST_ITEM dummy;
	LIST_ITEM *ptr = &dummy;
	dummy.next = *lst;

	if(lst == NULL || *lst == NULL || tgt == NULL)
	{
        return NULL;
	}

    while(ptr != NULL)
    {
        if(ptr->next == tgt)
        {
        	LIST_ITEM *retPtr = ptr->next;
            ptr->next = ptr->next->next;

            retPtr->next = NULL;
            *lst = dummy.next;

            return retPtr;
        }

        ptr = ptr->next;
    }

	return NULL;
}


WORD lengthOf(LIST_ITEM **lst)
{
	WORD length = 0;
	LIST_ITEM *ptr = *lst;

	while(ptr != NULL)
	{
		ptr = ptr->next;
		++length;
	}

	return length;
}

